/* 
** (Copyright) sejishikong <sejishikong@263.net>
** Authors:    sejishikong <sejishikong@263.net>
**             Wei Lian <lianwei2003.student@sina.com> 
** Maintainer: Wei Lian
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License Version 2 as
**    published by the Free Software Foundation;
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
*/

#include "sopcast.h"
#include "mylistitem.h"
#include "mypopupmenu.h"
#include "sys.h"
#include "config.h"
#include <qpainter.h>
#include <qmessagebox.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
////slots

void
Sopcast::sound_write (int i)
{
  sys->sound_write (i);
}

void
Sopcast::timerDone ()
{
  int value = sys->sound_read ();
  if (slidersound->value () != value)
    slidersound->setValue (value);
}


void
Sopcast::onplayerexit ()
{
  buttonplayer->setPaletteForegroundColor (Qt::black);
}


void
Sopcast::onsopexit ()
{
  statusbar->clear ();
  statuschannel->clear ();
}

void
Sopcast::parsestdout ()
{
  QString str, str1, str2, threadstate;
  str = QString (sop->readStdout ());
  if (str.contains ("detect MTU"))
    {
      statusbar->message (tr ("Connecting..."));
    }

  if (str.contains ("hook_sc"))
    {
      printf ("hook_sc\n");
      if (flaghook == FALSE)
	{
	  flaghook = TRUE;

	  if (!player->isRunning ())
	    {
	      if (forkplayer () == TRUE)
		buttonplayer->setPaletteForegroundColor (Qt::blue);
	      else
		fprintf (stderr, "failed to launch player!\n");
	    }
	  //launch statistics monitor
	  int sockfd = sys->connect_to_server ("127.0.0.1", atoi (outport));
	  snstatus =
	    new QSocketNotifier (sockfd, QSocketNotifier::Read, this);
	  connect (snstatus, SIGNAL (activated (int)),
		   SLOT (streamready (int)));
	  write (sockfd, "state\ns\n", sizeof ("state\ns\n"));
	  write (sockfd, "state\ns\n", sizeof ("state\ns\n"));
	}
    }
}

void
Sopcast::streamready (int fd)
{
  char buff[64];
  memset (buff, 0, sizeof (buff));

  int red = 0, size, ret;
  size = sizeof (buff);
  while (1)
    {
      ret =::read (fd, buff + red, size);
      if (ret <= 0)		///server shutdown
	{
	  if (ret < 0)
	    perror ("status socketnotifier");
	  ::close (fd);
	  snstatus->~QSocketNotifier ();
	  statusbar->clear ();
	  return;
	}
      if (strstr (buff, "\n"))
	break;

      red += ret;
      size -= ret;
    }

  if (buff[0] != 10)
    {
      char *savept;
      strtok_r (buff, "\n", &savept);

      int value[6];
      value[0] = atoi (strtok_r (buff, " ", &savept));
      for (int i = 1; i < 6; i++)
	value[i] = atoi (strtok_r (NULL, " ", &savept));

      sprintf (buff, "%3d%%,ur=%2dk,dr=%3dk,us=%2dk,ds=%3dk,peers=%2d",
	       value[0], value[1] / 1024, value[2] / 1024,
	       value[3] / 1024, value[4] / 1024, value[5]);

      statusbar->message (QString (buff));
    }
  else
    printf ("buff=10\n");
  write (fd, "s\n", sizeof ("s"));
}

void
Sopcast::recordstreamready (int fd)
{
  int ret;
  char buff[1024];
  ret =::read (fd, buff, sizeof (buff));
  if (ret <= 0)
    {
      if (ret < 0)
	perror ("record socketnotifier");
      buttonrecord->setPaletteForegroundColor (Qt::black);
      recordfp->close ();
      ::close (fd);
      snrecord->~QSocketNotifier ();
      return;
    }
  ::write (recordfp->handle (), buff, ret);
}

void
Sopcast::onbuttonrecordclicked ()
{
  if (buttonrecord->paletteForegroundColor () == Qt::black)
    {
      int sockfd = sys->connect_to_server ("127.0.0.1", atoi (outport));
      if (sockfd < 0)
	{
	  return;
	}
      ::write (sockfd, "1",::strlen ("1") + 1);
      char buf[19];
      if (::recv (sockfd, buf, sizeof (buf), 0) != sizeof (buf))
	{
	  fprintf (stderr, "err while parseing head\n");
	  ::close (sockfd);
	}
      int nread;
      ::ioctl (sockfd, FIONREAD, &nread);
      if (nread > 0)		////data availible
	{
	  QString data_path = vboxconfig->editrecorddir->text ();
	  QDir dir (data_path);
	  if (!dir.exists ())
	    dir.mkdir (data_path);
	  data_path += channelname.replace (QRegExp ("\\/+"), "#");	///eliminate harmful character
	  data_path += QDateTime::currentDateTime ().toString ();
	  data_path += ".asf";

	  recordfp->setName (data_path);
	  if (!recordfp->open (IO_WriteOnly))
	    {
	      perror ("record path is invalid");
	      ::close (sockfd);
	      return;
	    }

	  snrecord =
	    new QSocketNotifier (sockfd, QSocketNotifier::Read, this);
	  connect (snrecord, SIGNAL (activated (int)),
		   SLOT (recordstreamready (int)));

	  buttonrecord->setPaletteForegroundColor (Qt::red);
	}
    }
  else
    {
      if (recordfp->exists ())
	{
	  recordfp->close ();
	  ::close (snrecord->socket ());
	  snrecord->~QSocketNotifier ();
	  buttonrecord->setPaletteForegroundColor (Qt::black);
	}
    }
}


void
Sopcast::onconfigclicked ()
{
  vboxconfig->move (mapToGlobal (QPoint (0, 0)));
  vboxconfig->show ();
}

///-------------------------------------------------------
void
Sopcast::onrightbuttonclicked (QListViewItem * item,
			       const QPoint & pos, int cul)
{
  if (item)
    if (item->depth () == 1)
      {
//  popup->move (mapToGlobal (listchannel->itemRect (i).topLeft ()));//
	popup->move (pos);
	popup->
	  setText ("<table border=0 cellspacing=0 cellpadding=0><tr><td>" +
		   item->text (0) + "</td></tr></table><hr>"
		   "<table border=0 cellspacing=0 cellpadding=0>"
		   "<tr><td>Users: " + item->text (4) +
		   "</td><td>Visitors: " + item->text (5) +
		   "</td></tr>" "<tr><td>QualityC: " + item->text (7) +
		   "</td><td>QualityS: " + item->text (6) +
		   "</td></tr>" "<tr><td>MediaType: " + item->text (2) +
		   "</td><td>KBps: " + item->text (3) +
		   "</td></tr>" "<tr><td>StartFrom: " + item->text (8) +
		   "</td></tr></table><br>" + item->text (10));
	popup->adjustSize ();
	popup->show ();
      }
}

void
Sopcast::onmousemoved (QListViewItem * item)
{
  popup->hide ();		//close();
}

void
Sopcast::onlistitemclicked (QListViewItem * item)
{
  static int id = 1;
  if (item->depth () == 1)
    {
      killsop ();
      killplayer ();
      channelname = item->text (0);
      if (forksop (item->text (9)) == TRUE)
	{
	  statuschannel->message (item->text (0));
	  ///add to history
	  int index = 0;
	  bool flag = FALSE;
	  while (history->idAt (index) != -1)
	    {
//        printf ("index=%d,id=%d\n", index, history->idAt (index));
	      if (history->text (history->idAt (index)) ==
		  (item->text (0) + " " + item->text (9)))
		flag = TRUE;
	      index++;
	    }

	  if (flag == FALSE)
	    {
	      history->insertItem (item->text (0) + " " + item->text (9), id);
	      id++;
	    }
	}
      else
	fprintf (stderr, "failed to launch sp-sc!\n");
    }
}

///-------------------------------------------------------
void
Sopcast::onbuttonplayerclicked ()
{
  killplayer ();
  if (forkplayer () == TRUE)
    buttonplayer->setPaletteForegroundColor (Qt::blue);
  else
    fprintf (stderr, "failed to launch player!\n");
}

void
Sopcast::onbuttonstopclicked ()
{
  killsop ();
  killplayer ();
//  statusbar->clear ();
}

void
Sopcast::onbuttonquitclicked ()
{
  printf ("qsopcast exit\n");
  killsop ();
  killplayer ();
}

void
Sopcast::onbuttonexpandclicked ()
{
  bool flag;
  if (buttonexpand->paletteForegroundColor () == Qt::black)
    {
      flag = TRUE;
      buttonexpand->setPaletteForegroundColor (Qt::blue);
    }
  else
    {
      flag = FALSE;
      buttonexpand->setPaletteForegroundColor (Qt::black);
    }

  QListViewItem *myChild = listchannel->firstChild ();
  while (myChild)
    {
      if (flag)
	{
	  myChild->setOpen (TRUE);
	}
      else
	{
	  myChild->setOpen (FALSE);
	}

      myChild = myChild->nextSibling ();
    }
}

void
Sopcast::onbuttonsearchclicked ()
{
  bool flagfirst = TRUE;
  QListViewItem *item, *childitem;
  ////assign initial value
  if (listchannel->currentItem ()->depth () == 0)
    {
      item = listchannel->currentItem ();
      childitem = item->firstChild ();
    }
  else
    {
      childitem = listchannel->currentItem ();
      item = childitem->parent ();
      childitem = childitem->nextSibling ();
    }
  /////////find focus
  while (1)
    {
      while (childitem)
	{
	  if (childitem->text (0).contains (editsearch->text (), false)
	      && childitem->isEnabled ())
	    {
	      listchannel->setCurrentItem (childitem);
	      flagfirst = FALSE;
	      goto EXIT;
	    }
	  childitem = childitem->nextSibling ();
	}
      item = item->nextSibling ();
      if (!item)
	break;
      childitem = item->firstChild ();
    }
EXIT:;
  ////set color and find first focus if having failed finding focus so far
  item = listchannel->firstChild ();
  while (item)
    {
      bool flag = FALSE;
      childitem = item->firstChild ();
      while (childitem)
	{
	  if (childitem->text (0).contains (editsearch->text (), false)
	      && childitem->isEnabled ())
	    {
	      static_cast < MyListItem * >(childitem)->color = Qt::yellow;
	      childitem->repaint ();

	      flag = TRUE;
	      if (flagfirst == TRUE)
		{
		  listchannel->setCurrentItem (childitem);
		  flagfirst = FALSE;
		}
	    }
	  else
	    {
	      static_cast < MyListItem * >(childitem)->color = Qt::white;
	      childitem->repaint ();
	    }
	  childitem = childitem->nextSibling ();
	}

      if (flag)
	{
	  item->setOpen (TRUE);
	}
      else
	{
	  item->setOpen (FALSE);
	}

      item = item->nextSibling ();
    }
}

///---------------------------------------------
void
Sopcast::onchoosehistory (int i)
{

  QString str = history->text (i);
  QString name =
    str.mid (0, str.find (vboxconfig->editchannelheader->text ()));
  QString url = str.mid (str.find (vboxconfig->editchannelheader->text ()));
  //launch sop
  killsop ();
  killplayer ();
  channelname = name;
  if (forksop (url) == TRUE)
    statuschannel->message (name);
  else
    fprintf (stderr, "failed to launch sp-sc!\n");

}

void
Sopcast::onchoosebookmark (int id)
{
//  printf ("choose index=%d,id=%d\n", bookmark->indexOf (id), id);
  if (id >= 2)
    {
      if (bookmark->rightbutton)	///delete
	{
	  bookmark->removeItem (id);
	}
      else			///launch
	{
	  QString str = bookmark->text (id);
	  QString name =
	    str.mid (0, str.find (vboxconfig->editchannelheader->text ()));
	  QString url =
	    str.mid (str.find (vboxconfig->editchannelheader->text ()));
	  //launch sop
	  killsop ();
	  killplayer ();
	  channelname = name;
	  if (forksop (url) == TRUE)
	    statuschannel->message (name);
	  else
	    fprintf (stderr, "failed to launch sp-sc!\n");

	}
    }
}

void
Sopcast::onbookmarkclicked ()
{
  QListViewItem *item = listchannel->currentItem ();
  if (item->depth () == 1)
    {
      int index = 2;
      bool flag = FALSE;
      while (bookmark->idAt (index) != -1)
	{
//        printf ("index=%d,id=%d\n", index, bookmark->idAt (index));
	  if (bookmark->text (bookmark->idAt (index)) ==
	      (item->text (0) + " " + item->text (9)))
	    flag = TRUE;
	  index++;
	}

      if (flag == FALSE)
	{
	  bookmark->insertItem (item->text (0) + " " + item->text (9),
				idbookmark);
	  idbookmark++;
	}
    }
}

#include "mozart.xpm"
void
Sopcast::about ()
{
  const QPixmap p1 (mozart);
  QMessageBox m;
  m.setCaption ("qsopcast 0.2.1");
  m.setIconPixmap (p1);
  m.setText ("qsopcast: a QT front-end to p2p TV sopcast.\n"
	     "(c)2005-2006 Liu Di. All rights reserved.\n"
	     "Maintainer: Wei Lian\n"
	     "Developers: Liu Di, Wei Lian\n"
	     "http://lianwei3.googlepages.com/home2");
  m.exec ();
}
